package doc

import (
	"context"
	"strconv"
	"strings"

	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/blog/util"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/rpc/backendclient"
	"mall/service/blog/rpc/blogclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type DocumentListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewDocumentListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DocumentListLogic {
	return &DocumentListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *DocumentListLogic) DocumentList(req *types.DocumentListRequest) (resp *types.DocumentListResponse, err error) {
	logx.Infof("DocumentListRequest : %+v ", req)

	var page int64 = 1
	var pageSize int64
	if req.Current > 1 {
		page = req.Current
	}
	if req.PageSize > 0 { // 指定，检查最大值
		pageSize = req.PageSize
		if pageSize > l.svcCtx.Config.Query.MaxAmount {
			pageSize = l.svcCtx.Config.Query.MaxAmount
		}
	} else if req.PageSize == 0 { // 不指定，使用默认值
		pageSize = l.svcCtx.Config.Query.DefaultAmount
	} // 使用-1，rpc对应为0

	orderBys := util.ParseSorterNew(pointy.GetPointer(req.Sorter))
	filterBys := util.ParseFilterNew(pointy.GetPointer(req.Filter), nil)

	var termId int64
	if req.TermId != "" {
		ids := strings.Split(req.TermId, "-")
		for _, id := range ids {
			if i, err := strconv.ParseInt(id, 10, 64); err == nil {
				termId = i
			}
		}
	}
	res, err := l.svcCtx.BlogRpc.BackendGetKBPostList(l.ctx, &blogclient.TmpKBPostListReq{
		Page:      uint64(page),
		PageSize:  uint64(pageSize),
		Title:     pointy.GetPointer(req.Title),
		SectionId: pointy.GetPointer(uint64(termId)),
		Search:    pointy.GetPointer(req.Search),
		OrderBy:   orderBys,
		FilterBy:  filterBys,
	})
	if err != nil {
		return nil, err
	}

	var list []*types.Document
	var section string
	if len(res.List) > 0 {
		var uids []string
		for _, item := range res.List {
			uids = append(uids, strconv.FormatUint(*item.AuthorId, 10))
		}
		userList, err := l.svcCtx.BackendRpc.BackendGetUserList(l.ctx, &backendclient.UserListRequest{
			UserIds: strings.Join(uids, ","),
		})
		if err != nil {
			return nil, err
		}

		userMap := make(map[int64]string)
		if userList.Total > 0 {
			for _, user := range userList.List {
				if _, exist := userMap[user.Id]; !exist {
					userMap[user.Id] = user.Name
				}
			}
		}

		for _, item := range res.List {
			var tags []*types.PostTag
			if len(item.Tags) > 0 {
				for _, t := range item.Tags {
					tags = append(tags, &types.PostTag{
						Id:   int64(*t.Id),
						Name: *t.Name,
						Slug: *t.Slug,
					})
				}
			}
			var sections []*types.PostCategory
			if len(item.Sections) > 0 {
				for _, s := range item.Sections {
					sections = append(sections, &types.PostCategory{
						Id:   int64(*s.Id),
						Name: *s.Name,
						Slug: *s.Slug,
					})
					if termId == 0 || section != "" {
						continue
					}
					if *s.Id == uint64(termId) {
						section = *s.Name
					}
				}
			}
			var createdBy string
			if nickname, ok := userMap[int64(*item.AuthorId)]; ok {
				createdBy = nickname
			}
			list = append(list, &types.Document{
				Id:        int64(*item.Id),
				Title:     *item.Title,
				CreatedBy: createdBy,
				CreatedAt: *item.CreatedAt,
				UpdatedAt: *item.UpdatedAt,
				Sections:  sections,
				Tags:      tags,
			})
		}
	}

	return &types.DocumentListResponse{
		Current:  page,
		PageSize: pageSize,
		List:     list,
		Total:    int64(res.Total),
		Section:  section,
	}, nil
}
